package query;

import index.HashIndex;
import global.Minibase;
import parser.AST_Insert;
import relop.Schema;
import relop.Tuple;
import global.RID;
import heap.HeapFile;
import global.SearchKey;

/**
 * Execution plan for inserting tuples.
 */
class Insert implements Plan {
	protected IndexDesc[] indexes;
	protected String tableName;
	protected String columnName;
	protected Catalog catlog;
	protected Schema schema;
	protected Object[] values;

  /**
   * Optimizes the plan, given the parsed query.
   * 
   * @throws QueryException if table doesn't exists or values are invalid
   */
  public Insert(AST_Insert tree) throws QueryException {
    tableName = tree.getFileName();
    // check is table exists
    QueryCheck.tableExists(tableName);

    indexes = Minibase.SystemCatalog.getIndexes(tableName);
    // check if indexes exist
    for (IndexDesc index : indexes) {
      QueryCheck.indexExists(index.indexName);
    }
   
    // check if schema exists
    schema = Minibase.SystemCatalog.getSchema(tableName);
    if (schema == null) throw new QueryException("Invalid table Name");

    values = tree.getValues();
    // check if values are valid
    QueryCheck.insertValues(schema, values);
  } // public Insert(AST_Insert tree) throws QueryException

  /**
   * Executes the plan and prints applicable output.
   */
  public void execute() {
	HeapFile tableFile = new HeapFile(tableName);
    Tuple tuple = new Tuple(schema, values);
    // insert record
    RID rid = tableFile.insertRecord(tuple.getData());

    // if indexes are on table update them as well
    for (IndexDesc index : indexes) {
      HashIndex hIndex = new HashIndex(index.indexName);
      Object val = values[schema.fieldNumber(index.columnName)];
      SearchKey key = new SearchKey(val);
      hIndex.insertEntry(key, rid);
    }
    // print the output message
    System.out.println("1 rows affected.");

  } // public void execute()
} // class Insert implements Plan
